home *** CD-ROM | disk | FTP | other *** search
/ Mac Power 1997 December / MACPOWER-1997-12.ISO.7z / MACPOWER-1997-12.ISO / AMUG / PROGRAMMING / Raven 1.2 Examples.sit / Raven 1.2 Examples / Quill / Source / (Unused) / ResourceMap.cpp next >
C/C++ Source or Header  |  1997-08-07  |  16KB  |  647 lines

  1. /*
  2.  *  File:       ResourceMap.cpp
  3.  *  Summary:       A class that knows how to manage resources of a specified type. The
  4.  *                resource data is kept in memory so this class is unsuitable for large
  5.  *                resources. 
  6.  *  Written by: Jesse Jones
  7.  *
  8.  *  Copyright ゥ 1996 Jesse Jones. 
  9.  *    For conditions of distribution and use, see copyright notice in ZTypes.h  
  10.  *
  11.  *  Change History (most recent first):    
  12.  *
  13.  *         <->     8/15/96    JDJ        Created
  14.  */
  15.  
  16. #include "ResourceMap.h"
  17.  
  18. #include <Map.h>
  19.  
  20. #include <ZDragSession.h>
  21. #include <ZExceptions.h>
  22. #include <ZHandleStream.h>
  23. #include <ZLocker.h>
  24. #include <ZResUtils.h>
  25. #include <ZStream.h>
  26. #include <ZStringUtils.h>
  27.  
  28.  
  29. // ===================================================================================
  30. //    struct SResourceMapMessage
  31. // ===================================================================================
  32.  
  33. //---------------------------------------------------------------
  34. //
  35. // SResourceMapMessage::SResourceMapMessage
  36. //
  37. //---------------------------------------------------------------
  38. SResourceMapMessage::SResourceMapMessage(CResourceMap* rMap, ResID id, long mesg)
  39. {
  40.     ASSERT(rMap != nil);
  41.     
  42.     rsrcMap = rMap;
  43.     
  44.     if (mesg != kDeletingResources)
  45.         oldRsrc = newRsrc = rsrcMap->GetResource(id);
  46.     
  47.     message = mesg;
  48. }
  49.  
  50. #pragma mark -
  51.  
  52. //---------------------------------------------------------------
  53. //
  54. // SResource::SResource
  55. //
  56. //---------------------------------------------------------------
  57. SResource::SResource(const TDragSession& session, ItemReference item, FlavorType flavor)
  58. {
  59.     THandle data = session.GetData(item, flavor);
  60.     TInHandleStream stream(data);                
  61.         stream >> *this;
  62. }
  63.  
  64.  
  65. //---------------------------------------------------------------
  66. //
  67. // operator>> (SResource)
  68. //
  69. //---------------------------------------------------------------
  70. TInStream& operator>>(TInStream& stream, SResource& value)
  71. {
  72.     Handle hand = value.data;
  73.     
  74.     stream >> value.id >> value.name >> hand;
  75.  
  76.     return stream;
  77. }
  78.  
  79.  
  80. //---------------------------------------------------------------
  81. //
  82. // operator<< (SResource)
  83. //
  84. //---------------------------------------------------------------
  85. TOutStream& operator<<(TOutStream& stream, const SResource& value)
  86. {
  87.     stream << value.id << value.name << value.data;
  88.  
  89.     return stream;
  90. }
  91.  
  92.  
  93. //---------------------------------------------------------------
  94. //
  95. // SResource::AddData
  96. //
  97. //---------------------------------------------------------------
  98. void SResource::AddData(TDragSession& session, ItemReference item, FlavorType flavor, FlavorFlags flags) const
  99. {
  100.     THandle bits;
  101.  
  102.     {
  103.     TOutHandleStream stream(bits);                
  104.         stream << *this;
  105.     }
  106.  
  107.     {
  108.     TLocker lock(bits);
  109.         session.AddData(item, flavor, bits.GetPtr(), bits.GetSize(), flags);
  110.     }
  111. }
  112.  
  113. #pragma mark -
  114.  
  115. // ===================================================================================
  116. //    class CResourceMap::const_iterator
  117. // ===================================================================================
  118.  
  119. class MapIterator : public CResourceMap::ResourceMap::const_iterator {
  120.  
  121. public:
  122.     MapIterator()     {}
  123.  
  124.     MapIterator(const CResourceMap::ResourceMap::const_iterator& iter) : CResourceMap::ResourceMap::const_iterator(iter) {}
  125.  
  126.     MapIterator(CResourceMap::ResourceMap* resources) : CResourceMap::ResourceMap::const_iterator(resources->begin()) {}
  127.  
  128.     MapIterator(CResourceMap::ResourceMap* resources, int dummy) : CResourceMap::ResourceMap::const_iterator(resources->end()) {}
  129. };
  130.  
  131.  
  132. //---------------------------------------------------------------
  133. //
  134. // CResourceMap::const_iterator::~const_iterator
  135. //
  136. //---------------------------------------------------------------
  137. CResourceMap::const_iterator::~const_iterator()
  138. {
  139.     delete mIter;
  140. }
  141.  
  142.  
  143. //---------------------------------------------------------------
  144. //
  145. // CResourceMap::const_iterator::const_iterator (MapIterator)
  146. //
  147. //---------------------------------------------------------------
  148. CResourceMap::const_iterator::const_iterator(const MapIterator& iter)
  149. {
  150.     mIter = new MapIterator(iter);
  151. }
  152.  
  153.  
  154. //---------------------------------------------------------------
  155. //
  156. // CResourceMap::const_iterator::const_iterator (CResourceMap*)
  157. //
  158. //---------------------------------------------------------------
  159. CResourceMap::const_iterator::const_iterator(CResourceMap* rsrcMap)
  160. {
  161.     ASSERT(rsrcMap != nil);
  162.     
  163.     mIter = new MapIterator(rsrcMap->mResources->begin());
  164. }
  165.  
  166.  
  167. //---------------------------------------------------------------
  168. //
  169. // CResourceMap::const_iterator::const_iterator (const_iterator)
  170. //
  171. //---------------------------------------------------------------
  172. CResourceMap::const_iterator::const_iterator(const const_iterator& rhs)
  173. {
  174.     mIter = new MapIterator(*(rhs.mIter));
  175. }
  176.  
  177.                 
  178. //---------------------------------------------------------------
  179. //
  180. // CResourceMap::const_iterator::operator=
  181. //
  182. //---------------------------------------------------------------
  183. CResourceMap::const_iterator& CResourceMap::const_iterator::operator=(const const_iterator& rhs)
  184. {
  185.     if (*mIter != *(rhs.mIter)) {
  186.         MapIterator* temp = new MapIterator(*(rhs.mIter));
  187.  
  188.         delete mIter;
  189.         mIter = temp;
  190.     }
  191.     
  192.     return *this;
  193. }
  194.  
  195.  
  196. //---------------------------------------------------------------
  197. //
  198. // CResourceMap::const_iterator::operator==
  199. //
  200. //---------------------------------------------------------------
  201. bool CResourceMap::const_iterator::operator==(const const_iterator& rhs) const
  202. {
  203.     return *mIter == *(rhs.mIter);
  204. }
  205.             
  206.  
  207. //---------------------------------------------------------------
  208. //
  209. // CResourceMap::const_iterator::operator*
  210. //
  211. //---------------------------------------------------------------
  212. SResource CResourceMap::const_iterator::operator*() const
  213. {
  214.     const ResourceEntry& entry = **mIter;
  215.     
  216.     return SResource(entry.first, entry.second.name, entry.second.hand);
  217. }
  218.  
  219.  
  220. //---------------------------------------------------------------
  221. //
  222. // CResourceMap::const_iterator::operator++ ()
  223. //
  224. //---------------------------------------------------------------
  225. CResourceMap::const_iterator& CResourceMap::const_iterator::operator++()
  226. {
  227.     (*mIter)++;
  228.     
  229.     return *this;
  230. }
  231.             
  232.  
  233. //---------------------------------------------------------------
  234. //
  235. // CResourceMap::const_iterator::operator++ (int)
  236. //
  237. //---------------------------------------------------------------
  238. CResourceMap::const_iterator CResourceMap::const_iterator::operator++(int)
  239. {
  240.      CResourceMap::const_iterator temp = *this;
  241.      
  242.      ++*this;
  243.  
  244.      return temp;
  245. }
  246.  
  247. #pragma mark -
  248.  
  249. // ===================================================================================
  250. //    class CResourceMap
  251. // ===================================================================================
  252.  
  253. //---------------------------------------------------------------
  254. //
  255. // CResourceMap::~CResourceMap
  256. //
  257. //---------------------------------------------------------------
  258. CResourceMap::~CResourceMap()
  259. {
  260.     delete mResources;
  261. }
  262.  
  263.  
  264. //---------------------------------------------------------------
  265. //
  266. // CResourceMap::CResourceMap
  267. //
  268. //---------------------------------------------------------------
  269. CResourceMap::CResourceMap(ResType type)
  270. {
  271.     ASSERT(type != '????');
  272.     
  273.     mType = type;
  274.     mResources = new ResourceMap;
  275. }
  276.  
  277.  
  278. //---------------------------------------------------------------
  279. //
  280. // CResourceMap::ReadResources
  281. //
  282. //---------------------------------------------------------------
  283. void CResourceMap::ReadResources()
  284. {
  285.     // Zap any old resources that may be hanging around
  286.     if (mResources->size() > 0)
  287.         this->Broadcast(SResourceMapMessage(this, 0, kDeletingResources));
  288.     mResources->erase(mResources->begin(), mResources->end());
  289.  
  290.     // and read in the new resources.
  291.     short numViews = ::Count1Resources(mType);
  292.     for (short index = 1; index <= numViews; index++) {
  293.         Handle hand = ::Get1IndResource(mType, index);
  294.         ThrowIfResFail(hand);
  295.         
  296.         ResID   id;
  297.         ResType type;
  298.         Str255  name;
  299.         ::GetResInfo(hand, &id, &type, name);
  300.         ThrowIfResError();
  301.  
  302.         this->AddResource(SResource(id, PStrToStr(name), hand));
  303.     }
  304. }
  305.  
  306.  
  307. //---------------------------------------------------------------
  308. //
  309. // CResourceMap::WriteResources
  310. //
  311. // ・・・ハrewrite this so that an error while writing the new data
  312. // ・・・ハout doesn't trash all of the old data
  313. //
  314. //---------------------------------------------------------------
  315. void CResourceMap::WriteResources()
  316. {
  317.     // Out with the old...
  318.     Delete1Resource(mType);
  319.  
  320.     // and in with the new.
  321.     ResourceMap::iterator iter = mResources->begin();
  322.     while (iter != mResources->end()) {
  323.         ResourceEntry& entry = *iter++;
  324.         ResID id = entry.first;
  325.         SResourceData& data = entry.second;
  326.  
  327.         long size = data.hand.GetSize();
  328.         
  329.         Handle rsrc = ::NewHandle(size);
  330.         ThrowIfMemFail(rsrc);
  331.         
  332.         ::BlockMoveData(data.hand.GetUnsafePtr(), *rsrc, size);
  333.         ::AddResource(rsrc, mType, id, StrToPStr(data.name));
  334.         ThrowIfResError();
  335.  
  336.         ::ReleaseResource(rsrc);
  337.         
  338.         data.dirty = false;
  339.         this->Broadcast(SResourceMapMessage(this, id, kSavedResource));
  340.     }    
  341. }
  342.  
  343.  
  344. //---------------------------------------------------------------
  345. //
  346. // CResourceMap::GetNumResources
  347. //
  348. //---------------------------------------------------------------
  349. long CResourceMap::GetNumResources() const
  350. {
  351.     return mResources->size();
  352. }
  353.  
  354.  
  355. //---------------------------------------------------------------
  356. //
  357. // CResourceMap::GetLastResourceID
  358. //
  359. //---------------------------------------------------------------
  360. ResID CResourceMap::GetLastResourceID() const
  361. {
  362.     ResID lastID = 255;
  363.     
  364.     if (mResources->size() > 0) {
  365.         ResourceMap::reverse_iterator iter = mResources->rbegin();
  366.     
  367.         const ResourceEntry& entry = *iter++;
  368.         lastID = entry.first;
  369.     }    
  370.  
  371.     return lastID;
  372. }
  373.  
  374.  
  375. //---------------------------------------------------------------
  376. //
  377. // CResourceMap::GetResourceName
  378. //
  379. //---------------------------------------------------------------
  380. string CResourceMap::GetResourceName(ResID id) const
  381. {
  382.     ASSERT(mResources->count(id) == 1);
  383.  
  384.     const SResourceData& data = mResources->operator[](id);
  385.     
  386.     return data.name;
  387. }
  388.  
  389.  
  390. //---------------------------------------------------------------
  391. //
  392. // CResourceMap::GetResourceData
  393. //
  394. //---------------------------------------------------------------
  395. THandle CResourceMap::GetResourceData(ResID id) const
  396. {
  397.     ASSERT(mResources->count(id) == 1);
  398.  
  399.     const SResourceData& data = mResources->operator[](id);
  400.     
  401.     return data.hand;
  402. }
  403.  
  404.  
  405. //---------------------------------------------------------------
  406. //
  407. // CResourceMap::GetResource
  408. //
  409. //---------------------------------------------------------------
  410. SResource CResourceMap::GetResource(ResID id) const
  411. {
  412.     ASSERT(mResources->count(id) == 1);
  413.  
  414.     const SResourceData& data = mResources->operator[](id);
  415.     
  416.     return SResource(id, data.name, data.hand);
  417. }
  418.  
  419.  
  420. //---------------------------------------------------------------
  421. //
  422. // CResourceMap::IsDirty ()
  423. //
  424. //---------------------------------------------------------------
  425. bool CResourceMap::IsDirty() const
  426. {
  427.     bool dirty = false;
  428.     
  429.     ResourceMap::const_iterator iter = mResources->begin();
  430.     while (iter != mResources->end() && !dirty) {
  431.         const ResourceEntry& entry = *iter++;
  432.         const SResourceData& data = entry.second;
  433.         
  434.         dirty = data.dirty;
  435.     }    
  436.     
  437.     return dirty;
  438. }
  439.  
  440.  
  441. //---------------------------------------------------------------
  442. //
  443. // CResourceMap::IsDirty (ResID)
  444. //
  445. //---------------------------------------------------------------
  446. bool CResourceMap::IsDirty(ResID id) const
  447. {
  448.     ASSERT(mResources->count(id) == 1);
  449.  
  450.     const SResourceData& data = mResources->operator[](id);
  451.     
  452.     return data.dirty;
  453. }
  454.  
  455.  
  456. //---------------------------------------------------------------
  457. //
  458. // CResourceMap::ClearDirty ()
  459. //
  460. //---------------------------------------------------------------
  461. void CResourceMap::ClearDirty()
  462. {
  463.     ResourceMap::iterator iter = mResources->begin();
  464.     while (iter != mResources->end()) {
  465.         ResourceEntry& entry = *iter++;
  466.         SResourceData& data = entry.second;
  467.         
  468.         data.dirty = false;
  469.     }    
  470. }
  471.  
  472.  
  473. //---------------------------------------------------------------
  474. //
  475. // CResourceMap::ClearDirty (ResID)
  476. //
  477. //---------------------------------------------------------------
  478. void CResourceMap::ClearDirty(ResID id)
  479. {
  480.     ASSERT(mResources->count(id) == 1);
  481.  
  482.     SResourceData& data = mResources->operator[](id);
  483.     
  484.     data.dirty = false;
  485. }
  486.  
  487.  
  488. //---------------------------------------------------------------
  489. //
  490. // CResourceMap::SetResourceName
  491. //
  492. //---------------------------------------------------------------
  493. void CResourceMap::SetResourceName(ResID id, const string& newName)
  494. {
  495.     ASSERT(mResources->count(id) == 1);
  496.  
  497.     SResourceData& data = mResources->operator[](id);
  498.     if (data.name != newName) {
  499.         SResourceMapMessage mesg(this, id, kSetResourceName);
  500.         
  501.         data.name = newName;
  502.         data.dirty = true;
  503.         
  504.         mesg.newRsrc.name = newName;
  505.         this->Broadcast(mesg);
  506.     }
  507. }
  508.  
  509.  
  510. //---------------------------------------------------------------
  511. //
  512. // CResourceMap::SetResourceData
  513. //
  514. //---------------------------------------------------------------
  515. void CResourceMap::SetResourceData(ResID id, const THandle& newHand)
  516. {
  517.     ASSERT(mResources->count(id) == 1);
  518.  
  519.     SResourceData& data = mResources->operator[](id);
  520.  
  521.     if (newHand != data.hand) {
  522.     
  523.         // Do this the hard way to avoid invalidating objects that have
  524.         // a copy of data.hand    
  525.         long bytes = newHand.GetSize();
  526.         data.hand.SetSize(bytes);
  527.         BlockMoveData(newHand.GetUnsafePtr(), data.hand.GetUnsafePtr(), bytes);
  528.         
  529.         data.dirty = true;
  530.         
  531.         this->Broadcast(SResourceMapMessage(this, id, kSetResourceData));
  532.     }
  533. }
  534.  
  535.  
  536. //---------------------------------------------------------------
  537. //
  538. // CResourceMap::SetResourceID
  539. //
  540. //---------------------------------------------------------------
  541. void CResourceMap::SetResourceID(ResID oldID, ResID newID)
  542. {
  543.     ASSERT(mResources->count(oldID) == 1);
  544.  
  545.     if (oldID != newID) {
  546.         ASSERT(mResources->count(newID) == 0);
  547.  
  548.         SResourceMapMessage mesg(this, oldID, kSetResourceID);
  549.  
  550.         string name  = this->GetResourceName(oldID);
  551.         THandle data = this->GetResourceData(oldID);
  552.  
  553.         mResources->erase(oldID);
  554.         mResources->insert(ResourceEntry(newID, SResourceData(data, name, true)));
  555.         
  556.         mesg.newRsrc.id = newID;
  557.         this->Broadcast(mesg);
  558.     }
  559.     
  560.     ASSERT(mResources->count(newID) == 1);
  561. }
  562.  
  563.  
  564. //---------------------------------------------------------------
  565. //
  566. // CResourceMap::AddResource ()
  567. //
  568. //---------------------------------------------------------------
  569. ResID CResourceMap::AddResource()
  570. {
  571.     ResID id = this->GetLastResourceID() + 1;
  572.     ASSERT(mResources->count(id) == 0);
  573.         
  574.     mResources->insert(ResourceEntry(id, SResourceData(THandle(), "", true)));
  575.     
  576.     this->Broadcast(SResourceMapMessage(this, id, kAddedResource));
  577.     
  578.     return id;
  579. }
  580.  
  581.  
  582. //---------------------------------------------------------------
  583. //
  584. // CResourceMap::AddResource (SResource)
  585. // 
  586. //---------------------------------------------------------------
  587. void CResourceMap::AddResource(const SResource& rsrc)
  588. {
  589.     ASSERT(mResources->count(rsrc.id) == 0);
  590.     
  591.     mResources->insert(ResourceEntry(rsrc.id, SResourceData(rsrc.data, rsrc.name, true)));
  592.  
  593.     this->Broadcast(SResourceMapMessage(this, rsrc.id, kAddedResource));
  594. }
  595.  
  596.  
  597. //---------------------------------------------------------------
  598. //
  599. // CResourceMap::DeleteResource
  600. //
  601. //---------------------------------------------------------------
  602. void CResourceMap::DeleteResource(ResID id)
  603. {
  604.     ASSERT(mResources->count(id) == 1);
  605.  
  606.     SResourceMapMessage mesg(this, id, kDeletedResource);
  607.  
  608.     mResources->erase(id);
  609.     
  610.     this->Broadcast(mesg);
  611. }
  612.  
  613.  
  614. //---------------------------------------------------------------
  615. //
  616. // CResourceMap::HasResource
  617. //
  618. //---------------------------------------------------------------
  619. bool CResourceMap::HasResource(ResID id) const
  620. {
  621.     return mResources->count(id) == 1;
  622. }
  623.  
  624.  
  625. //---------------------------------------------------------------
  626. //
  627. // CResourceMap::begin
  628. //
  629. //---------------------------------------------------------------
  630. CResourceMap::const_iterator CResourceMap::begin() const
  631. {
  632.     return CResourceMap::const_iterator(mResources);
  633. }
  634.  
  635.  
  636. //---------------------------------------------------------------
  637. //
  638. // CResourceMap::end
  639. //
  640. //---------------------------------------------------------------
  641. CResourceMap::const_iterator CResourceMap::end() const
  642. {
  643.     return CResourceMap::const_iterator(MapIterator(mResources, 0));
  644. }
  645.  
  646.  
  647.